#ifndef _LOGGER_H_
#define _LOGGER_H_

#include "../sleipner_config.h"

#ifdef _LOGGER_MT_
#include "criticalsection.h"
#endif

//#include "file_io.h"

enum MSG_TYPE
{
    MSG_FATAL,
    MSG_ERROR,
    MSG_WARNING,
    MSG_INIT,
    MSG_LOAD,
    MSG_COMMENT,
    MSG_SCRIPT,
    MSG_TYPEC,
	MSG_INVALID
};

enum LOG_TYPE
{
    LOG_NONE        = 1 << 0,
    LOG_FILE        = 1 << 1,
    LOG_CONSOLE     = 1 << 2, 
    LOG_DEBUGWINDOW = 1 << 3,
    LOG_NETWORK		= 1 << 4,
    LOG_ALL_STREAMS = 0xFF,
    LOG_TYPE_LAST
};

// forward defines used in the string
#include <string>
namespace util
{
typedef int ( * ConsoleLogFunction ) ( const char * str );
class FileIO;
class Logger
{
public:
	static Logger&	Instance();
	void			Init(const std::string& LogName, bool Append = false);
	void			Shutdown();
	void			StartLine(MSG_TYPE Type, const char* Filename, int Line);
	void			EndLine();
	void			SetBehaviour(MSG_TYPE t, LOG_TYPE l);
	// config options
	void			SetVerbose(bool b)		{	m_Verbose = b; };
	void			SetAutoFlush(bool b)	{	m_AutoFlush = b; };
	void			SetConsoleCallback( ConsoleLogFunction func ) { m_pConFunc = func; };

	// Stream options
	Logger&	operator << (const std::string& d);
	Logger&	operator << (int				d);
	Logger&	operator << (long				d);
	Logger&	operator << (unsigned long		d);
	Logger&	operator << (unsigned int		d);
	Logger&	operator << (double				d);
	Logger&	operator << (signed long long	d);
	Logger&	operator << (unsigned long long	d);
	const std::string&	GetLogFile() const { return m_LogFile; };

	void			EnableStdOut(bool b) { m_OutputStdOut =b; };
private:
	Logger();
	~Logger();
    Logger( const Logger & );     // Not implemented to prevent copying.
    Logger & operator=( const Logger & );


	void		FlushData();
	void		FlushToFile();
	void		FlushToConsole();
	void		FlushToDebug();
	void		FlushToNetwork();
	void		AddData(const char*	Str);


	FileIO*		m_pFile;
	int			m_MessageMap[MSG_TYPEC];
	bool		m_Verbose;
	bool		m_AutoFlush;
	MSG_TYPE	m_CurrentType;

	// data folder
	char*			m_pData;
	unsigned int	m_MaxSize;
	unsigned int	m_CurrentSize;
	std::string		m_LogFile;
	
	ConsoleLogFunction m_pConFunc;
	bool			m_OutputStdOut;

#ifdef	_LOGGER_MT_	
	CriticalSection		m_CS;
#endif
};



}

#define _LOG(MESSAGE_TYPE, MSG)														\
	do {																			\
		util::Logger::Instance().StartLine(MESSAGE_TYPE, __FILE__, __LINE__ );		\
		util::Logger::Instance() << MSG;											\
		util::Logger::Instance().EndLine();											\
	} while (0)	


#endif // _LOGGER_H_